14 February 2019
Intel 8051 is a microcontroller unit developed in 1980s. On the off chance that you are writing Assembly code for this arcane technology, this post will exemplify a workflow on how to code, simulate and embed your program in a AT89S52/51 microchip.
We will be using an Arduino board to act as an ISP programmer. Pretty much any model will do, I will be using an Arduino Nano. Obviously, you will also need the IDE to program the Arduino board first. You could in theory do this with an USBasp, but for the device to support AT89S52 series, you have to update the firmware: which again requires an Arduino, so why not just cut the middle man.
AVRDUDE is a command
line utility which will be used to write the generated .hex
file in to the ROM of the microchip. You can install it with
brew install avrdude
. Since the default config file does
not support AT89S52, we will use a modified version provided by varun96.
It can be downloaded via the Instructables site, or directly here: F40R96CIUSLFZFP.conf. Put this
file somewhere accessible, we will later refer to it.
C51ASM is an assembler written by Atmel (which is now called
Microchip) for the 8051 architecture, supporting the AT89S52 we
are using. However, perhaps because of the acquirement by
Microchip, the link for the product http://www.atmel.com/tools/C51ASM.aspx
no longer works. Fortunately, by the magic of WayBackMachine, I
was able to connect to an archived version and download the executable.
Here
is the link for the archived webpage, and c51asm_macosx_1-2.zip is the
macOS version which can be directly downloaded. Make sure to extract the
files in the correct places, perhaps /usr/local/bin
and
usr/local/include
.
Jari Komppa’s 8051 emulator is a simple emulator which you can run in the Terminal since the UI is based on ncurses. The pre-built OSX Intel binary version worked fine for me. It achieves faster than real-time simulations which are great for simulating code such as a blinking LED etc…
Let us try to simulate this basic code, which sums decimal
3
and 4
and stores the result in the
A
(or ACC
) register of the chip.
ORG 0H
MOV A, #3
MOV R2, #4
ADD A, R2
END
First we have to assemble the code. Assuming that the file name is
sum.asm
:
~$ c51asm sum.asm
C51ASM: advanced C51 macro assembler Version 1.2 (06 May 2011)
Copyright (C) 2011 Atmel Corp.
Pass 1 completed with no warnings and no errors
Pass 2 completed with no warnings and no errors
Segment usage:
Code : 5 bytes
Data : 0 bytes
Idata : 0 bytes
Edata : 0 bytes
Fdata : 0 bytes
Xdata : 0 bytes
Bit : 0 bits
Register banks used: ---
Warnings: 0
Errors: 0
The assembler ran without any errors, and generated the file
sum.hex
which we will use to simulate the code. When you
run the 8051 emulator
you have downloaded, you will be
presented with a screen like this:
You can load the generated .hex
file by pressing
L
and entering the file name (sum.hex
in our
case).
Now the emulator will show the assembly code on the bottom left, and
the real-time values of various registers and memory elements. Since we
do not want to simulate this code in real-time, we can simply press
SPACE
to step the simulation. We can see the
assembly code executed and the results:
To run a simulation in real-time (or faster), you have to press
R
and adjust the simulation speed with +-
keys.
This code won’t be of much use when embedded in the microchip. Let us simulate another code, designed to blink a LED.
; LED blinker.
; total period = ((256 * 24 * PER) / 12000) milliseconds
; = 0.5 * PER milliseconds
; on-time = 0.25 * PER
ORG 0H
EQU PER EQU 2
MAIN: ACALL ON
ACALL DELAY
ACALL OFF
ACALL DELAY
AJMP MAIN
ON: SETB P1.0
RET
OFF: CLR P1.0
RET
DELAY: MOV R0, #PER ; generate delay, for 0.5 * PER ms
MOV R1, #0
LOOP: DJNZ R1, LOOP
, LOOP
DJNZ R0RET
END
As before, run as31 blink.asm
, and load the
.hex
file to the emulator. Satisfied with the simulation,
we can finally embed the program to the AT89S52.
First, we will have to configure the Arduino board to act as the ISP
programmer. To do this, open the Arduino IDE. Then open
File>Examples>ArduinoISP. This is the sketch we will be
uploading to the Arduino, but first, uncomment the line
#define USE_OLD_STYLE_WIRING
(You can alternatively use the
ICSP headers, but I have found this to be less problematic.) Go on and
click Upload and program the Arduino.
Now that we have configured the Arduino board, we have to make the
necessary connections. Before interconnecting the two chips, first put a
10 \mu F capacitor between the
RST
pin and GND
of the Arduino board. This
prevents the auto-reset function interfering with the programming we are
about to do. After that, the AT8952 chip requires a crystal oscillator
and some capacitors to function. This schematic from ernstc.dk shows the basic
idea:
After this, you have to wire the Arduino to the AT89S52. The
ArduinoISP sketch that we have uploaded has configured the pins 10 as
RESET
, 11 as MISO
, 12 as MOSI
and
13 as SCK
. This means that the connections are:
Arduino Pin | AT89S52 Pin |
---|---|
D10 (RESET) | 9 (RST) |
D11 (MISO) | 6 (MOSI) (P1.5) |
D12 (MOSI) | 7 (MISO) (P1.6) |
D13 (SCK) | 8 (SCK) (P1.7) |
5V | 40 (VCC), 31 (EA/VPP) |
GND | 20 (GND) |
After triple-checking the connections, it is time to flash the program to the microchip memory. The command will have the form:
avrdude \
-c stk500v1 \
-C PATH_TO_CONFIG_FILE -p 89s52 -b 19200 \
-P ARDUINO_PORT \ -U flash:w:PATH_TO_HEX_FILE
PATH_TO_CONFIG_FILE
is the path of the modified config
file F40R96CIUSLFZFP.conf
that we have downloaded. To find
which port your Arduino is connected to, check it in the Arduino IDE or
on a terminal enter ls /dev/cu.*
to list all connected
serial devices.
Make sure to check the output of this command; most importantly, it
has to return the correct device signature. If it returns
0x0000
, or Yikes! Invalid device signature.
,
check your connections again. DO NOT “use -F to override
this check.” After flashing the code, you can also verify it by
changing the letter w
(write) to v
(verify) in
the avrdude
command.
Assuming c51asm
points to the c51asm assembler,
emu
points to the 8051 emulator,
PATH_TO_CONFIG_FILE
is the location of the modified
F40R96CIUSLFZFP.conf
file and PATH_TO_ARDUINO
is the name of the serial port which the Arduino board is connected
(something like /dev/cu.usbserial-A9OZNH9X
in macOS), the
following utility summarizes the workflow.
#!/bin/bash
if [ "$1" == 'ass' ]; then
c51asm $2.asm -l --target AT89S52
elif [ "$1" == 'sim' ]; then
emu $2.hex
elif [ "$1" == 'prg' ]; then
avrdude -C PATH_TO_CONFIG_FILE -c stk500v1 -P `ARDUINO_PORT` -p 89s52 -b 19200 -U flash:w:$2.hex
else
echo "asm v1.1 -- @mlg556
Usage:
asm (ass | sim | prg)
Options:
ass Assemble using as32
sim Simulate the assembled .hex
prg Write .hex to flash"
fi